"""
字典可存储任意数量的相关信息不受限制
学习如何存储字典的列表，列表的字典和字典的字典
理解字典的基本概念，就能够更准确地为各种真实物建模

字典(dictionary)是一系列键值对(key-value pairs)，每个键都与一个值相关联
键和值之间用冒号分隔，键值对之间用逗号分隔
与键相关联的值可以是数字、字符串、列表乃至字典，可将任意Python对象用作字典中的值
在字典中，可将多个键值对存储在一个字典中，也可以在字典中嵌套字典
"""
print("--------------6.1 一个简单的字典-----------------")
alien_0 = {'color': 'green', 'points': 5}
print(alien_0['color'])
print(alien_0['points'])

print("--------------6.2 使用字典-----------------")
# 在Python中，字典用放在花括号{}中的一系列键值对表示
alien_0 = {'color': 'green'}
print(alien_0['color'])

print("--------------6.3 访问字典中的值-----------------")
alien_0 = {'color': 'green', 'points': 5}
new_points = alien_0['points']
print("You just earned " + str(new_points) + " points!")

print("--------------6.4 添加键值对-----------------")
# 字典是一种动态结构，可随时在其中添加键值对。
# 要添加键值对，可依次指定字典名、用方括号括起来的键和与该键关联的值。
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)

alien_0['name'] = 'zhangsan'
print(alien_0)

print("--------------6.5 创建一个空字典-----------------")
# 可先使用一对空花括号定义一个空字典，再分行添加各个键值对
alien_0 = {}
alien_0['color'] = 'green'
alien_0['points'] = 5
print(alien_0)

print("--------------6.6 修改字典中的值-----------------")
# 要修改字典中的值，可依次指定字典名、用方括号括起来的键和与该键关联的新值
alien_0 = {'color': 'green'}
print("The alien is " + alien_0['color'] + ".")

alien_0['color'] = 'yellow'
print("The alien is now " + alien_0['color'] + ".")

print("--------------6.7 删除键值对-----------------")
# 对于字典中不再需要的信息，可使用del语句将相应的键值对彻底删除
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)

del alien_0['points']
print(alien_0)

print("--------------6.8 由类似对象组成的字典-----------------")
# 由类似的对象组成的字典
# 可以使用字典来存储众多对象的同一种信息
# 例如，假设你要调查很多人，询问他们最喜欢的编程语言，可使用一个字典来存储这种结果
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}
print("Sarah's favorite language is " + favorite_languages['sarah'].title() + ".")

print("--------------6.9 使用get()来访问值-----------------")
# 你可以使用get()来访问值，这相比于方括号表示法的优点在于，
# 在指定的键不存在时，get()返回你指定的默认值，而不是引发错误
alien_0 = {'color': 'green', 'speed': 'slow'}
# 如果指定的键不存在，就将出错。
point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)

alien_0['points'] = 5
# 使用 get() 方法在指定的键不存在时返回一个默认值。
# get() 方法的第一个参数用于指定键，是必不可少的；
# 第二个参数为当指定的键不存在时要返回的值，是可选的
# 如果指定的键有可能不存在，应考虑使用 get() 方法，而不要使用方括号表示法
print(alien_0.get('points', 'No point value assigned.'))

# 在调用 get() 时，如果没有指定第二个参数且指定的键不存在，
# Python 将返回值 None，这个特殊的值表示没有相应的值。
# 这并非错误，None 只是一个表示所需值不存在的特殊值，第
print(alien_0.get('size'))

print("--------------6.10 遍历字典-----------------")
# 遍历字典时，键值对的返回顺序也与存储顺序不同
# Python不关心键值对的存储顺序，而只跟踪键和值之间的关联关系
# 遍历字典时，会默认遍历所有的键
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}
# 要编写遍历字典的 for 循环，可声明两个变量，分别用于存储键值对中的键和值。
# for 语句的第二部分包含字典名和方法 items()，这个方法返回一个键值对列表。
# 接下来，for 循环依次将每个键值对赋给指定的两个变量。在
for name, language in favorite_languages.items():
    # print(name.title() + "'s favorite language is " + language.title() + ".")
    print('\n' + name.title() + ': ' + language.title())

print("--------------6.11 遍历字典中的所有键-----------------")
# 遍历字典时，会默认遍历所有的键
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}
# keys() 方法很有用，它返回一个列表，其中包含字典中的所有键
for name in favorite_languages.keys():
    print(name.title())
# 在遍历字典时，会默认遍历所有的键。因此，如果将上述代码中的 for 语句替换为下面的代码，
# 输出将不变
for name in favorite_languages:
    print(name.title())

friends = ['phil', 'sarah']
for name in favorite_languages.keys():
    print(f"Hi, {name.title()}")

    if name in friends:
        print(" Hi " + name.title() +
              ", I see your favorite language is " +
              favorite_languages[name].title() + "!")

    if name not in friends:
        print(" Hi " + name.title() +
              ", I Dont Know Your Love Language")

print("--------------6.12 按顺序遍历字典中的所有键-----------------")
# 要以特定的顺序返回元素，一种办法是在 for 循环中对返回的键进行排序。
# 为此，可使用函数 sorted() 来获得按特定顺序排列的键列表的副本
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}

for name in sorted(favorite_languages.keys()):
    print(name.title())

print("--------------6.13 遍历字典中的所有值-----------------")
# 如果你感兴趣的是字典包含的值，可使用方法 values() ，它返回一个值列表，而不包含任何键。
# 字典可能包含重复的值
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}
for language in favorite_languages.values():
    print(language.title())

# 为删除重复项，可使用集合(set)。集合类似于列表，但每个元素都必须是独一无二的
print("--------------6.14 剔除重复项-----------------")
favorite_languages = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python'
}
for language in set(favorite_languages.values()):
    print(language.title())

print("--------------6.15 集合-----------------")
# 可以使用一对花括号直接创建集合，并在其中用逗号分隔元素
# 集合不会以特定的顺序存储元素，因此你对集合中元素的访问顺序也将不固定
# 集合和字典很容易混淆，因为它们都是用一对花括号定义的。
# 当花括号内没有键值对时，定义的很可能是集合。
languages = {'python', 'rust', 'python', 'c'}
print(languages)

print("--------------6.16 嵌套-----------------")
# 有时候，需要将一系列字典存储在列表中，或将列表作为值存储在字典中，
# 这称为嵌套。你可以在列表中嵌套字典、在字典中嵌套列表甚至在字典中嵌套字典。
# 列表中存储字典
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}

aliens = [alien_0, alien_1, alien_2]

# 遍历列表，并打印每个字典
for alien in aliens:
    print(alien)

print("--------------6.16.1 嵌套-往列表中添加字典-----------------")
# 创建一个空列表
aliens = []

# 遍历并往空列表中添加字典
for alien_number in range(30):
    # 定义一个字典
    new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
    # 往空列表中添加字典
    aliens.append(new_alien)

# 遍历列表，并打印每个字典
for alien in aliens[:5]:
    print(alien)

print("--------------6.16.2 嵌套-遍历中if判断并修改值-----------------")
# 遍历列表，并打印每个字典
for alien in aliens[:3]:
    # 判断并修改值
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10

# 遍历列表，并打印每个字典
for alien in aliens[:5]:
    print(alien)

print("--------------6.16.3 嵌套-遍历中if-eif判断并修改值-----------------")
# 遍历列表，并打印每个字典
for alien in aliens[:3]:
    # 判断并修改值
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10
    elif alien['color'] == 'yellow':
        alien['color'] = 'red'
        alien['speed'] = 'fast'
        alien['points'] = 15

# 遍历列表，并打印每个字典
for alien in aliens[:5]:
    print(alien)

print("--------------6.16.4 嵌套-遍历中if-eif-else判断并修改值-----------------")
# 创建一个空列表
aliens = []

# 遍历并往空列表中添加字典
for alien_number in range(30):
    # 定义一个字典
    new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
    # 往空列表中添加字典
    aliens.append(new_alien)

# 遍历列表，并打印每个字典
for alien in aliens[:3]:
    # 判断并修改值
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10
    elif alien['color'] == 'yellow':
        alien['color'] = 'red'
        alien['speed'] = 'fast'
        alien['points'] = 15
    else:
        alien['color'] = 'gray'
        alien['speed'] = 'slow'
        alien['points'] = 5

# 遍历列表，并打印每个字典
for alien in aliens[:5]:
    print(alien)

print("--------------6.17 在字典中存储列表-----------------")
# 有时候，需要将列表存储在字典中，而不是将字典存储在列表中。
# 这称为嵌套。你可以在字典中嵌套列表、在列表中嵌套字典甚至在字典中嵌套字典。

pizza = {
    'crust': 'thick',
    'toppings': ['mushrooms', 'extra cheese'],
}
# 概述所点的披萨
print("You ordered a " + pizza['crust'] + "-crust pizza " +
      "with the following toppings:")

for topping in pizza['toppings']:
    print("\t" + topping)

print("--------------6.17.1 在字典中嵌套列表-----------------")
# 每当需要在字典中将一个键关联到多个值时，都可以在字典中嵌套一个列表
favorite_languages = {
    'jen': ['python', 'ruby'],
    'sarah': ['c'],
    'edward': ['ruby', 'go'],
    'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items():
    # print("\n" + name.title() + "'s favorite languages are:")
    print(name.title() + ":" + str(languages))
    # 多层循环
    for language in languages:
        print("\t" + language.title())

print("--------------6.18 在字典中存储字典-----------------")
# 有时候，需要将一系列字典存储在列表中，或将列表作为值存储在字典中，
# 这称为嵌套。你可以在字典中嵌套列表、在列表中嵌套字典甚至在字典中嵌套字典。

users = {
    'aeinstein': {
        'first': 'albert',
        'last': 'einstein',
        'location': 'princeton',
    },
    'mcurie': {
        'first': 'marie',
        'last': 'curie',
        'location': 'paris',
    }
}
# 遍历字典
for username, user_info in users.items():
    print("\nUsername: " + username)
    full_name = user_info['first'] + " " + user_info['last']
    location = user_info['location']
    print("\tFull name: " + full_name.title())
    print("\tLocation: " + location.title())
